#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <time.h>
#include <math.h>
#include <errno.h>

#include "cJSON.h"
#include "common.h"
#include "simulator.h"
#include "log.h"
#include "heartbeat.h"

// 发送心跳函数
static int simulatorSendHeartbeat(void *arg) {
    SimulatorContext *context = (SimulatorContext *)arg;
    
    if (context->sockfd <= 0) {
        return -1;
    }
    
    cJSON *root = cJSON_CreateObject();
    cJSON_AddStringToObject(root, "type", "heartbeat");
    cJSON_AddNumberToObject(root, "timestamp", time(NULL));
    
    char *jsonStr = cJSON_PrintUnformatted(root);
    int ret = sendPacket(context->sockfd, DATA_TYPE_HEARTBEAT, jsonStr);
    
    free(jsonStr);
    cJSON_Delete(root);
    
    if (ret < 0) {
        logError("Failed to send heartbeat");
        return -1;
    }
    
    logDebug("Heartbeat sent");
    return 0;
}

// 接收服务器响应
static void *receiveResponse(void *arg) {
    SimulatorContext *context = (SimulatorContext *)arg;
    char jsonBuffer[MAX_BUFFER_SIZE];
    unsigned char dataType;
    
    while (context->running) {
        int ret = recvPacket(context->sockfd, jsonBuffer, MAX_BUFFER_SIZE, &dataType);
        if (ret > 0) {
            cJSON *root = cJSON_Parse(jsonBuffer);
            if (root) {
                switch (dataType) {
                    case DATA_TYPE_ACK:
                        logInfo("Received ACK from server");
                        break;
                    case DATA_TYPE_ERROR:
                        {
                            char *message = cJSON_GetObjectItem(root, "message")->valuestring;
                            logError("Received ERROR from server: %s", message);
                        }
                        break;
                    default:
                        logWarning("Received unknown data type: %d", dataType);
                        break;
                }
                cJSON_Delete(root);
            } else {
                logError("Failed to parse response from server");
            }
        } else if (ret == 0 || errno != EAGAIN) {
            logError("Connection to server closed or error occurred");
            context->running = 0;
            break;
        }
        
        usleep(100000);  // 100ms
    }
    
    return NULL;
}

// 生成随机硅片数据
void generateRandomSiliconWaferData(SimulatorContext *context) {
    const char *defectTypes[] = {"无缺陷", "隐裂", "碎片", "色差", "污染"};
    const char *equipmentIds[] = {"EQ001", "EQ002", "EQ003", "EQ004", "EQ005"};
    const char *lineNumbers[] = {"LINE-01", "LINE-02", "LINE-03", "LINE-04", "LINE-05"};
    const char *ipAddresses[] = {"192.168.2.101", "192.168.2.102", "192.168.2.103", "192.168.2.145", "192.168.2.156"};
    const char *reworkFlags[] = {"未返工", "已返工"};
    
    // 生成批次大小
    int batchSize = rand() % MAX_WAFER_BATCH_SIZE + 1;
    
    cJSON *root = cJSON_CreateObject();
    cJSON *batchArray = cJSON_CreateArray();
    
    for (int i = 0; i < batchSize; i++) {
        cJSON *item = cJSON_CreateObject();
        
        // 生成硅片ID
        char waferId[20];
        sprintf(waferId, "sw%08d", rand() % 100000000);
        cJSON_AddStringToObject(item, "waferId", waferId);
        
        // 随机选择设备ID
        cJSON_AddStringToObject(item, "equipmentId", equipmentIds[rand() % 5]);
        
        // 随机选择IP地址
        cJSON_AddStringToObject(item, "ipAddress", ipAddresses[rand() % 5]);
        
        // 随机选择缺陷类型
        cJSON_AddStringToObject(item, "defectType", defectTypes[rand() % 5]);
        
        // 生成随机效率 (18.0 - 22.0)
        double efficiency = 18.0 + ((double)rand() / RAND_MAX) * 4.0;
        cJSON_AddNumberToObject(item, "efficiency", efficiency);
        
        // 生成随机重量 (2.3 - 2.5)
        double weight = 2.3 + ((double)rand() / RAND_MAX) * 0.2;
        cJSON_AddNumberToObject(item, "weight", weight);
        
        // 生成随机时间
        time_t now = time(NULL);
        time_t randomTime = now - (rand() % 86400);  // 过去24小时内的随机时间
        struct tm *tm = localtime(&randomTime);
        char timeStr[20];
        strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", tm);
        cJSON_AddStringToObject(item, "productionTime", timeStr);
        
        // 随机选择产线
        cJSON_AddStringToObject(item, "productionLineNo", lineNumbers[rand() % 5]);
        
        // 随机选择返工标志
        cJSON_AddStringToObject(item, "reworkFlag", reworkFlags[rand() % 2]);
        
        cJSON_AddItemToArray(batchArray, item);
    }
    
    cJSON_AddItemToObject(root, "batchSiliconWaferData", batchArray);
    
    char *jsonStr = cJSON_PrintUnformatted(root);
    
    logInfo("Sending %d random silicon wafer data records to server", batchSize);
    int ret = sendPacket(context->sockfd, DATA_TYPE_SILICON_WAFER, jsonStr);
    if (ret < 0) {
        logError("Failed to send silicon wafer data");
    } else {
        logInfo("Silicon wafer data sent successfully");
    }
    
    free(jsonStr);
    cJSON_Delete(root);
}

// 生成随机生产数据（符合production_data表结构）
void generateRandomProductionData(SimulatorContext *context) {
    const char *defectTypes[] = {"无缺陷", "隐裂", "碎片", "色差", "污染"};
    const char *equipmentIds[] = {"EQ001", "EQ002", "EQ003", "EQ004", "EQ005"};
    const char *lineNumbers[] = {"产线01", "产线02", "产线03", "产线04", "产线05"};
    const char *ipAddresses[] = {"192.168.2.101", "192.168.2.102", "192.168.2.103", "192.168.2.145", "192.168.2.156"};
    const char *reworkFlags[] = {"未返工", "已返工"};
    
    cJSON *root = cJSON_CreateObject();
    cJSON *prodData = cJSON_CreateObject();
    
    // 生成硅片ID
    char waferId[20];
    sprintf(waferId, "sw%08d", rand() % 100000000);
    cJSON_AddStringToObject(prodData, "waferid", waferId);
    
    // 随机选择设备ID
    cJSON_AddStringToObject(prodData, "equipmentid", equipmentIds[rand() % 5]);
    
    // 随机选择缺陷类型
    cJSON_AddStringToObject(prodData, "defecttyme", defectTypes[rand() % 5]);
    
    // 随机选择产线
    cJSON_AddStringToObject(prodData, "productionline", lineNumbers[rand() % 5]);
    
    // 随机选择返工标志
    cJSON_AddStringToObject(prodData, "reworkflag", reworkFlags[rand() % 2]);
    
    // 随机选择IP地址
    cJSON_AddStringToObject(prodData, "idaddress", ipAddresses[rand() % 5]);
    
    cJSON_AddItemToObject(root, "productionData", prodData);
    
    char *jsonStr = cJSON_PrintUnformatted(root);
    
    logInfo("Sending random production data to server");
    int ret = sendPacket(context->sockfd, DATA_TYPE_PRODUCTION, jsonStr);
    if (ret < 0) {
        logError("Failed to send production data");
    } else {
        logInfo("Production data sent successfully");
    }
    
    free(jsonStr);
    cJSON_Delete(root);
}

// 生成随机生产统计数据
void generateRandomProductionSummary(SimulatorContext *context) {
    const char *shifts[] = {"白班", "夜班"};
    const char *lineNumbers[] = {"产线01", "产线02", "产线03", "产线04", "产线05"};
    
    cJSON *root = cJSON_CreateObject();
    cJSON *summaryData = cJSON_CreateObject();
    
    // 随机选择班次
    cJSON_AddStringToObject(summaryData, "shift", shifts[rand() % 2]);
    
    // 生成时间（小时级）
    time_t now = time(NULL);
    struct tm *tm = localtime(&now);
    char timeStr[14];
    strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:00", tm);
    cJSON_AddStringToObject(summaryData, "time", timeStr);
    
    // 随机选择产线
    cJSON_AddStringToObject(summaryData, "lineno", lineNumbers[rand() % 5]);
    
    // 生成随机产量 (15000 - 20000)
    int output = 15000 + rand() % 5001;
    cJSON_AddNumberToObject(summaryData, "output", output);
    
    // 生成随机合格率 (0.95 - 0.995)
    double qualifiedRate = 0.95 + ((double)rand() / RAND_MAX) * 0.045;
    cJSON_AddNumberToObject(summaryData, "qualifiedrata", qualifiedRate);
    
    // 生成随机A品率 (0.85 - 0.95)
    double aGradeRate = 0.85 + ((double)rand() / RAND_MAX) * 0.10;
    cJSON_AddNumberToObject(summaryData, "Agraderata", aGradeRate);
    
    // 生成随机返工率 (0.005 - 0.03)
    double reworkRate = 0.005 + ((double)rand() / RAND_MAX) * 0.025;
    cJSON_AddNumberToObject(summaryData, "reworkrata", reworkRate);
    
    cJSON_AddItemToObject(root, "productionSummary", summaryData);
    
    char *jsonStr = cJSON_PrintUnformatted(root);
    
    logInfo("Sending random production summary data to server");
    int ret = sendPacket(context->sockfd, DATA_TYPE_PRODUCTION, jsonStr);
    if (ret < 0) {
        logError("Failed to send production summary data");
    } else {
        logInfo("Production summary data sent successfully");
    }
    
    free(jsonStr);
    cJSON_Delete(root);
}

// 数据生成线程
static void *generateDataThread(void *arg) {
    SimulatorContext *context = (SimulatorContext *)arg;
    
    while (context->running) {
        // 随机选择发送的数据类型
        int dataType = rand() % 2;
        
        if (dataType == 0) {
            generateRandomSiliconWaferData(context);
        } else {
            generateRandomProductionData(context);
        }
        
        // 等待一段时间后再次发送
        sleep(SIMULATION_INTERVAL);
    }
    
    return NULL;
}

// 主函数
int main() {
    SimulatorContext context;
    pthread_t receiveThread;
    
    // 初始化随机数种子
    srand(time(NULL));
    
    // 初始化日志
    logInit("simulator.log", LOG_LEVEL_INFO, 1);
    logInfo("Starting simulator...");
    
    // 连接服务器
    context.sockfd = connectTCPServer(SERVER_IP, SERVER_PORT);
    if (context.sockfd < 0) {
        logFatal("Failed to connect to server %s:%d", SERVER_IP, SERVER_PORT);
    }
    
    logInfo("Connected to server %s:%d", SERVER_IP, SERVER_PORT);
    
    // 初始化心跳
    context.heartbeat = heartbeatInit(HEARTBEAT_INTERVAL, HEARTBEAT_TIMEOUT, 
                                     simulatorSendHeartbeat, &context);
    if (!context.heartbeat) {
        logError("Failed to initialize heartbeat");
    } else {
        heartbeatStart(context.heartbeat);
        logInfo("Heartbeat started with interval %d seconds", HEARTBEAT_INTERVAL);
    }
    
    // 设置运行标志
    context.running = 1;
    
    // 启动接收线程
    pthread_create(&receiveThread, NULL, receiveResponse, &context);
    
    // 启动数据生成线程
    pthread_create(&context.dataThread, NULL, generateDataThread, &context);
    
    // 运行一段时间后退出
    logInfo("Simulator running, press Ctrl+C to exit");
    sleep(300);  // 运行5分钟
    
    // 清理资源
    logInfo("Stopping simulator...");
    context.running = 0;
    
    if (context.heartbeat) {
        heartbeatStop(context.heartbeat);
        heartbeatDestroy(context.heartbeat);
    }
    
    pthread_join(receiveThread, NULL);
    pthread_join(context.dataThread, NULL);
    close(context.sockfd);
    logCleanup();
    
    logInfo("Simulator stopped");
    return 0;
}